/**
 * @Author: 陈瑞鹏
 * @Date:   2022-10-14 17:05:51
 * @Last Modified by:   陈瑞鹏
 * @Last Modified time: 2023-10-31 15:25:17
 */

import abiao_utils from "abiao_utils";
import { NextFunction, Request, Response } from "express";
import { start } from "pm2";
import configDefault from "../config/config.default";
import { Code } from "../enum/code.enum";
import BlackIp from "../models/common/blackIp.model";
import Switch from "../models/common/switch.model";
import RequestLogs from "../models/log/requestLog.model";
import User from "../models/user/user.model";
import JWT from "../utils/jwt";
import Result from "../utils/result";
import utils from "../utils/utils";

//中间件
export default class middleware {

  /**
   * 拦截
   */
  static async intercept(req: Request | any, res: any, next: NextFunction) {
    let ip = utils.getClientIp(req);
    let BlackRes: any = await BlackIp.findOne({ ip });

    if (BlackRes) {
      throw new Result(Code.Fail, `无法进入...`);
    }

    let SwitchRes: any = await Switch.findOne({ name: "server" });

    if (!SwitchRes.isOpen) {
      throw new Result(Code.Fail, '服务器维护中.....');
    }

    return next();
  }

  /**
   * 请求日志
   * @param req 
   * @param res 
   * @param next 
   */
  static async requestLogs(req: Request | any, res: any, next: NextFunction) {
    let startTime = new Date().getTime();
    req._startTime = new Date(); //

    let calResponseTime = async () => {
      let endTime = new Date().getTime();
      let now: any = new Date();
      let deltaTime = now - req._startTime;

      let info = {
        openId: req.headers['openid'],
        originalUrl: req.originalUrl,
        referer: req.headers['referer'],
        method: req.method,
        statusCode: res.statusCode,
        ip: utils.getClientIp(req),
        parameter: req.body ? (typeof req.body.data == 'string' ? req.body : req.body) : req.query,
        handletTime: deltaTime,
        pmId: process.env.pm_id,
        mem: process.memoryUsage(),
        reqTimestamp: startTime,
        resTimestamp: endTime,
        createTime: abiao_utils.date(),
        createTtl: new Date().getTime(),
      }
      await RequestLogs.create(info);
    }

    await res.once('close', calResponseTime);

    return await next();
  }

  /**
   * 初始化开关
   */
  static async init_switch() {
    let switchName = [
      { name: 'pay', desc: '支付开关', isOpen: true },
      { name: 'server', desc: '服务器开关', isOpen: true },
    ]
    for (const interator of switchName) {
      let SwitchRes: any = await Switch.findOne({ name: interator.name });
      if (!SwitchRes) {
        await Switch.create(interator);
      }
    }
  }

  /**
   * 获取开关
   * @param name 
   * @returns 
   */
  static async getSwitch(name: string) {
    let SwitchRes: any = await Switch.findOne({ name });
    if (SwitchRes) {
      return SwitchRes.isOpen;
    } else {
      Switch.create({ name, isOpen: false });
      return false;
    }
  }

  static async check_api_token(req: Request, res: Response, next: NextFunction) {
    const { authorization, timestamp, sign } = req.headers
    const skip_url: string[] = ['/login/qhLogin', '/login/enterGame', '/server/getServerList', '/game/enterGame', '/game/createRoom', '/game/doStart', '/game/getRoomRes', '/game/saveDrawData2', '/guard/enterGame', '/guard/setState', '/guard/unLock', '/guard/getTreasure', '/guard/openTreasure', '/guard/accelerate', '/guard/getReward', '/guard/integral', '/guard/victory', '/guard/guide', '/guard/sendEmail', '/guard/lqEmail', '/guard/yjLq', '/guard/yjDel', '/guard/getEmailList', '/guard/delEmail', '/guard/exchange', '/guard/updateNickName', '/guard/sign', '/guard/rankList', '/guard/getData', '/guard/bagUpdate', '/guard/updateDailyTask', '/guard/receiveDailyTask', '/guard/settlement', '/guard/consumeTalentDiamond'];

    if (skip_url.includes(req.originalUrl) || req.method == 'GET') {
      return next()
    }

    const key: string = configDefault.qhApiQuery.lkey;
    // let key = 'tests'

    let str: string = authorization + key + timestamp;
    let flag: string = abiao_utils.md5(str);

    if (flag != sign) {
      throw new Result(Code.Fail, '签名错误');
    }

    let nowTime = new Date().getTime();
    if (nowTime - Number(timestamp) > 10000) {
      throw new Result(Code.Fail, '请求时间错误');
    }

    let SwitchRes: any = await Switch.findOne({ name: 'server' });
    if (!SwitchRes.isOpen) {
      throw new Result(Code.Fail, '服务器维护中');
    }

    const info: any = JWT.verify(<string>authorization);
    if (info) {
      let UserData: any = await User.findOne({ roleId: info.roleId })
      if (!UserData) {
        throw new Result(Code.Fail, '角色错误');
      }

      if (!UserData.status) {
        throw new Result(Code.Fail, '账号被封禁');
      }

      let userToken: any = JWT.verify(UserData.token);
      if (info.roleId != userToken.roleId) {
        throw new Result(Code.Fail, '参数错误');
      }
    } else {
      throw new Result(Code.Fail, '参数错误!!!');
    }
    return next()
  }
}